﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Resources;
using System.Xml.Linq;
using System.IO;
using System.Runtime.Serialization;

namespace Rachmans.Sabang
{
    public class DataSourceLoader
    {
        public Dictionary<int, quranPagesPage> Pages { get { return _pages; } }
        public Dictionary<string, quranSurasSura> Suras { get { return _suras; } }
        public Dictionary<string, quranJuzsJuz> Juzs { get { return _juzs; } }
        public Dictionary<string, quranSura> Quran { get { return _quran; } }
        public Dictionary<int, Number> Numbers { get { return _numbers; } }
        public Dictionary<string, Translation> Translations { get { return _translations; } }
        Dictionary<int, quranPagesPage> _pages = new Dictionary<int, quranPagesPage>();
        Dictionary<string, quranSurasSura> _suras = new Dictionary<string, quranSurasSura>();
        Dictionary<string, quranJuzsJuz> _juzs = new Dictionary<string, quranJuzsJuz>();
        Dictionary<string, quranSura> _quran = new Dictionary<string, quranSura>();
        Dictionary<int, Number> _numbers = new Dictionary<int, Number>();
        Dictionary<string, Translation> _translations = new Dictionary<string, Translation>();

        int MAX_PAGE = 604;
        int MAX_SURA = 114;

        public void LoadDictionaries()
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/Dictionaries.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);

            //  Load Numbers.
            IEnumerable<XElement> searched = from n in appDataXml.Elements("Numbers").Elements("Number")
                                             select n;
            //  Get the value for ayat that need to be loaded.
            foreach (var n in searched)
            {
                //  Check pages again if page already exist.
                if (!_numbers.ContainsKey((int)n.Element("Index")))
                {
                    Number number = new Number { Index = (int)n.Element("Index"), Value = (string)n.Element("Value") };
                    _numbers.Add(number.Index, number);
                }
            }

            //  Load Translations.
            searched = from n in appDataXml.Elements("Translations").Elements("Translation")
                                             select n;
            //  Get the value for ayat that need to be loaded.
            foreach (var n in searched)
            {
                //  Check pages again if page already exist.
                if (!_translations.ContainsKey((string)n.Element("Language")))
                {
                    Translation translation = new Translation { Language = (string)n.Element("Language"), FlowDirection = (string)n.Element("FlowDirection"), Font = (string)n.Element("Font"), Text = (string)n.Element("Text") };
                    _translations.Add(translation.Language, translation);
                }
            }
        
        }

        public void LoadPage(int page)
        {
            // Load number.
            LoadDictionaries();

            // Declare an XElement to hold the contents of the xml file. 
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-data.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched;

            if (!_pages.ContainsKey(page) || !_pages.ContainsKey(page+1))
            {
                if (page < MAX_PAGE)
                {
                    //  Get current and next page.
                    searched = from p in appDataXml.Elements("pages").Elements("page")
                               where (int)p.Attribute("index") == page || (int)p.Attribute("index") == page + 1
                               select p;
                }
                else
                {
                    //  Get current page.
                    searched = from p in appDataXml.Elements("pages").Elements("page")
                               where (int)p.Attribute("index") == page
                               select p;
                }

                //  Get the value for ayat that need to be loaded.
                foreach (var p in searched)
                {
                    //  Check pages again if page already exist.
                    if (!_pages.ContainsKey((int)p.Attribute("index")))
                    {
                        quranPagesPage quranPage = new quranPagesPage { aya = (string)p.Attribute("aya"), index = (string)p.Attribute("index"), sura = (string)p.Attribute("sura") };
                        _pages.Add((int)p.Attribute("index"), quranPage);
                    }
                }
            }

            int sura1 = Int32.Parse(_pages[page].sura);
            int sura2;

            //  Load Suras.
            if (page < MAX_PAGE)
            {
                //  Load sura in one page after.
                sura2 = Int32.Parse(_pages[page + 1].sura);
            }
            else
            {
                sura2 = MAX_SURA;
            }

            //  Get current sura.
            if (sura1 != sura2)
            {
                searched = from p in appDataXml.Elements("suras").Elements("sura")
                           where (int)p.Attribute("index") >= sura1 && (int)p.Attribute("index") <= sura2
                           select p;
            }
            else
            {
                searched = from p in appDataXml.Elements("suras").Elements("sura")
                           where (int)p.Attribute("index") == sura1
                           select p;
            }

            //  Get the value for ayat that need to be loaded.
            foreach (var p in searched)
            {
                string index = (string)p.Attribute("index");

                if (!_suras.ContainsKey(index))
                {
                    quranSurasSura quranSura = new quranSurasSura { ayas = (string)p.Attribute("ayas"), index = index, name = (string)p.Attribute("name")
                        , tname = (string)p.Attribute("tname")};
                    _suras.Add(index, quranSura);
                }
            }

            //  Load ayas.
            xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-uthmani.xml", UriKind.Relative));
            appDataXml = XElement.Load(xml.Stream);

            ////  Get current and next page.
            //IEnumerable<XElement> searchedAyas;

            if (page <= MAX_PAGE)
            {
                //  Check sura for requested page and next page. If sura is different then query only requested page.
                if (sura1 != sura2)
                {
                    searched = from s in appDataXml.Elements("sura")
                               where (int)s.Attribute("index") >= sura1 && (int)s.Attribute("index") <= sura2
                               select s;
                }
                else
                {
                    searched = from s in appDataXml.Elements("sura")
                               where (int)s.Attribute("index") == sura1
                               select s;
                }

                foreach (var s in searched)
                {
                    //  Check pages again if page already exist.
                    if (!_quran.ContainsKey((string)s.Attribute("index")))
                    {
                        quranSura sura = new quranSura { name = (string)s.Attribute("name"), index = (string)s.Attribute("index") };
                        List<quranSuraAya> ayas = new List<quranSuraAya>();

                        //  Populate ayas.
                        foreach (var a in s.Elements("aya"))
                        {
                            quranSuraAya aya = new quranSuraAya { bismillah = (string)a.Attribute("bismillah"), index = (string)a.Attribute("index"), text = (string)a.Attribute("text") };
                            ayas.Add(aya);
                        }

                        sura.aya = ayas.ToArray();

                        _quran.Add((string)s.Attribute("index"), sura);
                    }
                }
            }

            //  SHOW the aya here.
        }

        public int LoadSuraStartPage(int sura)
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-data.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched = from p in appDataXml.Elements("pages").Elements("page")
                                             where (int)p.Attribute("sura") <= sura || (int)p.Attribute("sura") >= sura
                       select p;

            int prevSura = 0;
            int prevPage = 0;
            //  Get the value for ayat that need to be loaded.
            foreach (var p in searched)
            {
                if ((int)p.Attribute("sura") == sura)
                {
                    if ((int)p.Attribute("aya") == 1)
                    {
                        LoadPage((int)p.Attribute("index"));
                        return (int)p.Attribute("index");
                    }
                    else
                    {
                        LoadPage(prevPage);
                        return prevPage;
                    }
                }
                else if ((int)p.Attribute("sura") < sura)
                {
                    prevSura = (int)p.Attribute("sura");
                    prevPage = (int)p.Attribute("index");
                }
            }

            LoadPage(prevPage);
            return prevPage;
        }

        public void LoadSuras()
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-data.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched = from s in appDataXml.Elements("suras").Elements("sura")
                                                        select s;

            foreach (var s in searched)
            {
                string index = (string)s.Attribute("index");

                if (!_suras.ContainsKey(index))
                {
                    quranSurasSura quranSura = new quranSurasSura
                    {
                        ayas = (string)s.Attribute("ayas"),
                        index = index,
                        name = (string)s.Attribute("name")
                        ,
                        tname = (string)s.Attribute("tname")
                    };
                    _suras.Add(index, quranSura);
                }
            }
        }

        public void LoadQuran(int sura)
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-uthmani.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched = from s in appDataXml.Elements("sura")
                                             where (int)s.Attribute("index") == sura
                                             select s;

            foreach (var s in searched)
            {
                //  Check pages again if page already exist.
                //if (!_quran.ContainsKey((string)s.Attribute("index")))
                //{
                    quranSura qSura = new quranSura { name = (string)s.Attribute("name"), index = (string)s.Attribute("index") };
                    List<quranSuraAya> ayas = new List<quranSuraAya>();

                    //  Populate ayas.
                    foreach (var a in s.Elements("aya"))
                    {
                        quranSuraAya aya = new quranSuraAya { bismillah = (string)a.Attribute("bismillah"), index = (string)a.Attribute("index"), text = (string)a.Attribute("text") };
                        ayas.Add(aya);
                    }

                    qSura.aya = ayas.ToArray();

                    _quran.Add((string)s.Attribute("index"), qSura);
                //}
            }
        }

        public void LoadJuzs()
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-data.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched = from j in appDataXml.Elements("juzs").Elements("juz")
                                             select j;

            foreach (var j in searched)
            {
                string index = (string)j.Attribute("index");

                if (!_juzs.ContainsKey(index))
                {
                    quranJuzsJuz quranJuz = new quranJuzsJuz
                    {
                        index = index,
                        aya = (string)j.Attribute("aya"),
                        sura = (string)j.Attribute("sura"),
                        words = (string)j.Attribute("words")
                    };
                    _juzs.Add(index, quranJuz);
                }
            }
        }

        public void LoadPagesBetween(int sura, int aya1, int aya2)
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-data.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched = from p in appDataXml.Elements("pages").Elements("page")
                                             where (int)p.Attribute("sura") == sura && ((int)p.Attribute("aya") >= aya1 && (int)p.Attribute("aya") <= aya2)
                                             select p;

            foreach (var p in searched)
            {
                int index = (int)p.Attribute("index");

                if (!_pages.ContainsKey(index))
                {
                    quranPagesPage quranPage = new quranPagesPage
                    {
                        index = (string)p.Attribute("index"),
                        aya = (string)p.Attribute("aya"),
                        sura = (string)p.Attribute("sura")
                    };

                    _pages.Add(index, quranPage);
                }
            }
        }

        public void LoadPagesUntil(int sura, int aya)
        {
            StreamResourceInfo xml = Application.GetResourceStream(new Uri("/Rachmans.Sabang;component/Xml/quran-data.xml", UriKind.Relative));
            XElement appDataXml = XElement.Load(xml.Stream);
            IEnumerable<XElement> searched = from p in appDataXml.Elements("pages").Elements("page")
                                             where ((int)p.Attribute("sura") == sura || (int)p.Attribute("sura") == sura - 1) && ((int)p.Attribute("aya") >= aya || (int)p.Attribute("aya") <= aya)
                                             select p;

            foreach (var p in searched)
            {
                int index = (int)p.Attribute("index");

                if (!_pages.ContainsKey(index))
                {
                    quranPagesPage quranPage = new quranPagesPage
                    {
                        index = (string)p.Attribute("index"),
                        aya = (string)p.Attribute("aya"),
                        sura = (string)p.Attribute("sura")
                    };

                    _pages.Add(index, quranPage);
                }
            }
        }
    }
}
